﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using System.Threading;
using System.Collections;

namespace Srvtools
{
    public class RecordLock
    {
        public RecordLock()
        { 
        
        }

        public static string RecordFileName = SystemFile.RecordLockFile;

        public enum LockType
        { 
            Idle,
            Deleting,
            Updating,
            Other
        }

        private static XmlNode FindAlias(XmlDocument xml, string DBAlias)
        {
            XmlNodeList xnl = xml.DocumentElement.SelectNodes("DataBase");
            for (int i = 0; i < xnl.Count; i++)
            {
                if (xnl[i].Attributes["Alias"].Value == DBAlias)
                {
                    return xnl[i];
                }
            }
            return null;
        }

        private static XmlNode FindTable(XmlNode xml, string TableName)
        {
            XmlNodeList xnl = xml.SelectNodes("Table");
            for (int i = 0; i < xnl.Count; i++)
            {
                if (xnl[i].Attributes["Name"].Value == TableName)
                {
                    return xnl[i];
                }
            }
            return null;
        }

        private static XmlNode FindRecord(XmlNode xml, string KeyFields, string KeyValues)
        {
            XmlNodeList xnl = xml.SelectNodes("Record");
            for (int i = 0; i < xnl.Count; i++)
            {
                if (xnl[i].Attributes["KeyFields"].Value == KeyFields && xnl[i].Attributes["KeyValues"].Value == KeyValues)
                {
                    return xnl[i];
                }
            }
            return null;
        }

        //creat DBAlias, Table, Record node
        private static XmlNode CreatRecord(XmlDocument xml, string DBAlias, string TableName, string KeyFields, string KeyValues, string UserID)
        {
            return CreatRecord(xml, DBAlias, TableName, KeyFields, KeyValues, UserID, LockType.Updating);
        }
        private static XmlNode CreatRecord(XmlDocument xml, string DBAlias, string TableName, string KeyFields, string KeyValues, string UserID, LockType lt)
        {
            XmlElement nodeDBAlias = xml.CreateElement("DataBase");
            XmlAttribute attAlias = xml.CreateAttribute("Alias");
            attAlias.Value = DBAlias;
            nodeDBAlias.Attributes.Append(attAlias);
            xml.DocumentElement.AppendChild(nodeDBAlias);
            return CreatRecord(xml, nodeDBAlias, TableName, KeyFields, KeyValues, UserID, lt);// call creat Table, Record node
        }

        //creat Table, Record node
        private static XmlNode CreatRecord(XmlDocument xml, XmlNode nodeDBAlias, string TableName, string KeyFields, string KeyValues, string UserID)
        {
            return CreatRecord(xml, nodeDBAlias, TableName, KeyFields, KeyValues, UserID, LockType.Updating);
        }
        //creat Table, Record node
        private static XmlNode CreatRecord(XmlDocument xml, XmlNode nodeDBAlias, string TableName, string KeyFields, string KeyValues, string UserID, LockType lt)
        {
            XmlElement nodeTable = xml.CreateElement("Table");
            XmlAttribute attName = xml.CreateAttribute("Name");
            attName.Value = TableName;
            nodeTable.Attributes.Append(attName);
            nodeDBAlias.AppendChild(nodeTable);
            return CreatRecord(xml, nodeTable, KeyFields, KeyValues, UserID, lt);// call creat Record node
        }


        //creat Record node
        private static XmlNode CreatRecord(XmlDocument xml, XmlNode nodeTable, string KeyFields, string KeyValues, string UserID)
        {
            return CreatRecord(xml, nodeTable, KeyFields, KeyValues, UserID, LockType.Updating);
        }
        //creat Record node
        private static XmlNode CreatRecord(XmlDocument xml, XmlNode nodeTable, string KeyFields, string KeyValues, string UserID, LockType lt)
        {
            XmlElement nodeRecord = xml.CreateElement("Record");
            XmlAttribute attKeyFields = xml.CreateAttribute("KeyFields");
            attKeyFields.Value = KeyFields;
            nodeRecord.Attributes.Append(attKeyFields);
            XmlAttribute attKeyValues = xml.CreateAttribute("KeyValues");
            attKeyValues.Value = KeyValues;
            nodeRecord.Attributes.Append(attKeyValues);
            XmlAttribute attUserID = xml.CreateAttribute("UserID");
            attUserID.Value = UserID;
            nodeRecord.Attributes.Append(attUserID);
            XmlAttribute attStatus = xml.CreateAttribute("Status");
            switch (lt)
            {
                case LockType.Updating: attStatus.Value = "Updating"; break;
                case LockType.Deleting: attStatus.Value = "Deleting"; break;
                default: attStatus.Value = ""; break;
            }
            nodeRecord.Attributes.Append(attStatus);
            nodeTable.AppendChild(nodeRecord);
            xml.Save(RecordFileName);
            return nodeRecord;
        }


        public static LockType AddRecordLock(string DBAlias, string TableName, string KeyFields, string KeyValues, string UserID)
        {
            return AddRecordLock(DBAlias, TableName, KeyFields, KeyValues, UserID, LockType.Updating);
        }

        public static LockType AddRecordLock(string DBAlias,string TableName, string KeyFields, string KeyValues, string UserID, LockType lt)
        {
            //while (lockinuse)
            //{
            //    Thread.Sleep(100);
            //}
            LockType retval;
            //lockinuse = true;
            XmlDocument xml = new XmlDocument();
            xml.Load(RecordFileName);
            XmlNode nodeDBAlias = FindAlias(xml, DBAlias);
            if (nodeDBAlias == null)
            {
                CreatRecord(xml, DBAlias, TableName, KeyFields, KeyValues, UserID, lt);
                return LockType.Idle;
            }
            else
            {
                XmlNode nodeTable = FindTable(nodeDBAlias, TableName);
                if(nodeTable == null)
                {
                    CreatRecord(xml, nodeDBAlias, TableName, KeyFields, KeyValues, UserID, lt);
                    retval = LockType.Idle;
                }
                else
                {
                    XmlNode nodeRecord = FindRecord(nodeTable, KeyFields, KeyValues);
                    if (nodeRecord == null)
                    {
                        CreatRecord(xml, nodeTable, KeyFields, KeyValues, UserID, lt);
                        retval = LockType.Idle;
                    }
                    else
                    {
                        if (nodeRecord.Attributes["UserID"].Value == UserID)
                        {
                            switch (lt)
                            {
                                case LockType.Updating: nodeRecord.Attributes["Status"].Value = "Updating"; break;
                                case LockType.Deleting: nodeRecord.Attributes["Status"].Value = "Deleting"; break;
                                default: nodeRecord.Attributes["Status"].Value = ""; break;
                            }
                            retval = LockType.Idle;
                            xml.Save(RecordFileName);
                        }
                        else
                        {
                            switch (nodeRecord.Attributes["Status"].Value)
                            {
                                case "Updating": retval = LockType.Updating; break;
                                case "Deleting": retval = LockType.Deleting; break;
                                default: retval = LockType.Other; break;
                            }
                        }
                    }
                
                }
            }
            //lockinuse = false;
            return retval;
        }

        public static void RemoveRecordLock(string DBAlias, string TableName, string KeyFields, ArrayList KeyValues, string UserID)
        {
            XmlDocument xml = new XmlDocument();
            xml.Load(RecordFileName);
            XmlNode nodeDBAlias = FindAlias(xml, DBAlias);
            if (nodeDBAlias == null)
            {
                return;
            }
            else
            { 
                 XmlNode nodeTable = FindTable(nodeDBAlias, TableName);
                 if (nodeTable == null)
                 {
                     return;
                 }
                 else
                 {
                     for (int i = 0; i < KeyValues.Count; i++)
                     {
                         RemoveRecordLock(nodeTable, KeyFields, KeyValues[i].ToString(), UserID);
                     }
                     xml.Save(RecordFileName);
                 }
            
            }

        }

        public static void RemoveRecordLock(XmlNode nodeTable, string KeyFields, string KeyValues, string UserID)
        {
            XmlNode nodeRecord = FindRecord(nodeTable, KeyFields, KeyValues);
            if (nodeRecord == null)
            {
                return;
            }
            else
            {
                if (nodeRecord.Attributes["UserID"].Value == UserID)
                {
                    nodeTable.RemoveChild(nodeRecord);
                }
                else
                {
                    return;
                }
            }
        
        
        }

        public static void CreateRecordFile()
        {
            //if (File.Exists(RecordFileName))
            //{
            //    File.Delete(RecordFileName);
            //}
            FileStream xmlstream = new FileStream(RecordFileName, FileMode.Create);
            XmlTextWriter w = new XmlTextWriter(xmlstream, new System.Text.UnicodeEncoding());
            w.Formatting = Formatting.Indented;
            w.WriteStartElement("InfoLight");
            w.WriteEndElement();
            w.Close();
            xmlstream.Close();
        }

        public static void ClearRecordFile()
        {
            XmlDocument xml = new XmlDocument();
            xml.Load(RecordFileName);
            xml.DocumentElement.RemoveAll();
            xml.Save(RecordFileName);
        }

        public static void ClearRecordFile(string UserID)
        {
            XmlDocument xml = new XmlDocument();
            xml.Load(RecordFileName);
            XmlNodeList xnldb = xml.DocumentElement.SelectNodes("DataBase");
            foreach (XmlNode xndb in xnldb)
            {
                XmlNodeList xnltable = xndb.SelectNodes("Table");
                foreach (XmlNode xntable in xnltable)
                {
                    XmlNodeList xnlrecord = xntable.SelectNodes("Record");
                    foreach (XmlNode xnrecord in xnlrecord)
                    {
                        if (xnrecord.Attributes["UserID"].Value == UserID)
                        {
                            xntable.RemoveChild(xnrecord);
                        }
                    }
                }
            }
            xml.Save(RecordFileName);
        }






    }
}
